#include "hbhttpclient.h"
#include <QEventLoop>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QRegExp>
#include <QTextCodec>
#include <QTimer>

HBHttpClient::HBHttpClient(QObject *parent) : QObject(parent) {}

void HBHttpClient::setHttpType(HBHttpClient::HttpType type) { m_type = type; }

void HBHttpClient::setUrlStr(QString urlStr) { m_urlStr = urlStr; }

void HBHttpClient::setHeaders(QMap<QString, QString> headers) {
  m_headers.clear();

  QStringList keys = headers.keys();
  for (int i = 0; i < keys.count(); i++) {
    QString k = keys[i];
    m_headers[k] = headers[k];
  }
}

void HBHttpClient::addHeader(QString key, QString value) {
  m_headers[key] = value;
}

void HBHttpClient::setParams(QVariantMap params) {
  m_params.clear();

  QStringList keys = params.keys();
  for (int i = 0; i < keys.count(); i++) {
    QString k = keys[i];
    m_params[k] = params[k];
  }
}

void HBHttpClient::addParam(QString key, QVariant value) {
  m_params[key] = value;
}

void HBHttpClient::setTimeout(int timeoutSeconds) {
  m_timeout = timeoutSeconds;
}

void HBHttpClient::resume() {

  QNetworkRequest request;

  QStringList ks = m_headers.keys();
  for (int i = 0; i < ks.count(); i++) {
    QString k = ks[i];
    QString v = m_headers[k];
    request.setRawHeader(k.toUtf8(), v.toUtf8());
  }

  QString urlStr = m_urlStr;
  QByteArray body;

  if (m_type == Get) {

    if (m_urlStr.endsWith("?")) {
      urlStr = QString("%1%2").arg(m_urlStr, m_queryBody());
    } else {
      urlStr = QString("%1?%2").arg(m_urlStr, m_queryBody());
    }
  } else if (m_type == Post) {
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    body = m_postBody();
  } else if (m_type == Form) {
    request.setHeader(QNetworkRequest::ContentTypeHeader,
                      "application/x-www-form-urlencoded");

    body = m_queryBody();
  }

  request.setUrl(QUrl(urlStr));

  QNetworkAccessManager manager;
  QNetworkReply *reply;

  if (m_type == Get) {
    reply = manager.get(request);
  } else {
    reply = manager.post(request, body);
  }

  QEventLoop loop;
  connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);

  QTimer timer;
  connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
  timer.start(m_timeout * 1000);

  loop.exec();
  if (timer.isActive()) {
    timer.stop();
  }

  m_code = reply->error();
  m_responseMsg = reply->errorString();

  if (m_code == QNetworkReply::NoError) {
    m_responseByte = reply->readAll();

    QJsonDocument doc = QJsonDocument::fromJson(m_responseByte);

    m_response = doc.object();
  } else {
    m_response = QJsonObject();
    m_responseByte.clear();
  }

  reply->deleteLater();
}

int HBHttpClient::responseCode() { return m_code; }

QString HBHttpClient::responseErrorString() { return m_responseMsg; }

QJsonObject HBHttpClient::responseBody() { return m_response; }

QByteArray HBHttpClient::responseData() { return m_responseByte; }

QByteArray HBHttpClient::m_queryBody() {
  QStringList list;
  QStringList keys = m_params.keys();

  QTextCodec *codec = QTextCodec::codecForName("utf-8");
  QRegExp reg("[\u4e00-\u9fa5]");

  for (int i = 0; i < keys.count(); i++) {
    QString key = keys[i];
    QString v = m_params[key].toString();

    bool hasChinese = reg.indexIn(v) >= 0;

    if (hasChinese) {
      QByteArray byte = codec->fromUnicode(v);
      byte = byte.toPercentEncoding();

      QString str = QString("%1=%2").arg(key).arg(byte.data());
      list << str;
    } else {
      QString str = QString("%1=%2").arg(key).arg(v);
      list << str;
    }
  }

  return list.join("&").toStdString().c_str();
}

QByteArray HBHttpClient::m_postBody() {
  QJsonDocument doc = QJsonDocument::fromVariant(m_params);
  return doc.toJson(QJsonDocument::Compact);
}
